package com.gollum.jpa.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gollum.jpa.dao.JpaDao;
import com.gollum.jpa.domain.Page;
import com.gollum.jpa.util.QueryUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import javax.persistence.LockModeType;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * jpaservice
 *
 * @author Herther
 * @version 1.0.0
 * @ClassName JpaServerImpl.java
 * @createTime 2022年08月07日 17:55:00
 */
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = {Exception.class})
@SuppressWarnings("all")
public class JpaServerImpl<T,ID extends Serializable> implements JpaServer<T,ID> {

    private static Logger log = LoggerFactory.getLogger(JpaServerImpl.class);

    @Autowired
    protected JpaDao<T,ID> dao;

    protected Class<T> domainClass;


    public JpaServerImpl() {
       this.domainClass = ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
    }

    @Override
    public Page<T> findAllWithPage(Page<T> page, Specification<T> specification) {
        return dao.findAllWithPage(page, specification);
    }

    @Override
    public Page<T> findAllWithPage(Page<T> page) {
        return dao.findAllWithPage(page);
    }


    @Override
    public List<T> findAll() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<T> domains = dao.findAll();
        stopWatch.stop();
        log.info("查询耗时: {}",stopWatch.getTotalTimeMillis());
        return domains;
    }

    @Override
    public List<T> findAll(Specification<T> specification, String sorts) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<T> domains = dao.findAll(specification, QueryUtils.buildSort(sorts));
        stopWatch.stop();
        log.info("查询耗时: {}",stopWatch.getTotalTimeMillis());
        return domains;
    }

    @Override
    public List<T> findAll(String sorts) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<T> domains = dao.findAll(QueryUtils.buildSort(sorts));
        stopWatch.stop();
        log.info("查询耗时: {}",stopWatch.getTotalTimeMillis());
        return domains;
    }

    @Override
    public List<T> findAll(Sort sort) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<T> domains = dao.findAll(sort);
        stopWatch.stop();
        log.info("查询耗时: {}",stopWatch.getTotalTimeMillis());
        return domains;
    }

    @Override
    public List<T> findAll(Specification<T> specification, Sort sort) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<T> domains = dao.findAll(specification, sort);
        stopWatch.stop();
        log.info("查询耗时: {}",stopWatch.getTotalTimeMillis());
        return domains;
    }

    @Override
    public T getById(ID id) {
        return dao.getById(id);
    }

    @Override
    public T getByIdLock(ID id, LockModeType lockModeType) {
        return dao.findById(id, lockModeType);
    }

    @Override
    public T save(T entity) {
        return dao.save(entity);
    }


    /**
     * 对象转 map 对象
     *
     * @param values 对象
     * @return map对象
     * @auther: Herther
     * @since 1.0.0
     * @date: 2022/9/14 21:03
     */
    public Map<String,Object> objectToMap(Object values){
        ObjectMapper mapper = new ObjectMapper(); //转换器
        return mapper.convertValue(values, Map.class);
    }

    @Override
    public List<T> saveInBatch(Iterable<T> entitys) {
        return dao.saveInBatch(entitys);
    }

    @Override
    public long count() {
        return dao.count();
    }

    @Override
    public boolean exits(ID id) {
        return dao.existsById(id);
    }

    @Override
    public boolean isNew(T entity) {
        return dao.isNew(entity);
    }

    @Override
    public void removeById(ID id) {
        dao.deleteById(id);
    }

    @Override
    public void remove(T entity) {
        dao.delete(entity);
    }

    @Override
    public void removeAll(Iterable<T> entitys) {
        dao.deleteAll(entitys);
    }

    @Override
    public void removeAllByIds(Iterable<ID> ids) {
        dao.deleteAllById(ids);
    }

    @Override
    public boolean logic(ID id) {
        return dao.logic(id);
    }

    /**
     * 获取是否符合Between 的连接
     *
     * @param value1 参数1
     * @param value2 参数2
     * @return 是否符合
     * @auther: Herther
     * @since 1.0.0
     * @date: 2022/9/17 21:06
     */
    public boolean getBetweenCondition(Object value1 ,Object value2){
        return Objects.nonNull(value1) && Objects.nonNull(value2) ? true : false;
    }

    /**
     * 降序
     * 如果实体里面有sort 根据Sort字段进行DESC排序
     * @param Sort
     * @auther: Herther
     * @since 1.0.0
     * @date: 2022/10/11 0:16
     */
    public Sort getDescSort(){
        return QueryUtils.buildSort("sort:desc");
    }

    /**
     * 升序
     * 如果实体里面有sort 根据Sort字段进行ASC排序
     * @param Sort
     * @auther: Herther
     * @since 1.0.0
     * @date: 2022/10/11 0:16
     */
    public Sort getAscSort(){
        return QueryUtils.buildSort("sort:asc");
    }


    //public Specification<T> buildParams(Class paramsClazz,Object valueParams,String filter){
    //    if(Objects.isNull(valueParams)){
    //        return null;
    //    }
    //    Map<String, Object> params = objectToMap(valueParams);
    //    return  QueryUtils.buildSpecificationByEntityParams(paramsClazz, params,filter);
    //}

    //@Override
    //public T getOneById(ID id) {
    //    Optional<T> optional = dao.findById(id);
    //    return optional.isPresent() ? optional.get() : null;
    //}
    //
    //@Override
    //public T getOneByIdLock(ID id, LockModeType lockModeType) {
    //    return dao.findById(id, lockModeType);
    //}
    //
    //@Override
    //public Page<T> findAllWithPage(Page<T> page, Map<String, Object> params) {
    //    return dao.findAllWithPage(page, params);
    //}
    //
    //@Override
    //public Page<T> findAllWithPage(Page<T> page, SuperQueryCustom params) {
    //    return dao.findAllWithPage(page, params);
    //}
    //
    //
    //@Override
    //public List<T> findAll(Map<String, Object> params, String... sort) {
    //    return null;
    //}
    //
    //@Override
    //public List<T> findAll() {
    //    return dao.findAll();
    //}
    //@Override
    //public T save(T entity) {
    //    //Field clientCode = ReflectionUtils.findField(entity.getClass(), "clientCode");
    //    //        AnnotationUtils.getAnnotation()
    //    //TODO 后期通过 子类上的注解参数进行注入版本号
    //    //ReflectionUtils.setField(clientCode, entity, 100L);
    //    return this.dao.save(entity);
    //}
    //
    //
    //
    //
    //@Override
    //public List<T> saveAll(Iterable<T> entits) {
    //    return null;
    //}
    //

    //
    //@Override
    //public List<T> saveInBatch(Iterable<T> entits) {
    //    return null;
    //}
    //

    //
    //@Override
    //public void deleteById(ID id) {
    //     dao.removeById(id);
    //}
    //
    //@Override
    //public void delete(T entity) {
    //    dao.remove(entity);
    //}
    //
    //@Override
    //public void noLogicDeleteById(ID id) {
    //    dao.deleteById(id);
    //}
    //
    //@Override
    //public void deleteById(Iterable<ID> ids) {
    //    dao.removeAllById(ids);
    //}
    //
    //@Override
    //public void deleteNoLogicById(Iterable<ID> ids) {
    //    dao.deleteAllById(ids);
    //}
    //
    //@Override
    //public void deleteNoLogic(T entity) {
    //    dao.delete(entity);
    //}
    //
    //@Override
    //public void deleteAll(Iterable<T> entities) {
    //    dao.removeAll(entities);
    //}
    //
    //@Override
    //public void deleteNoLogicAll(Iterable<T> entities) {
    //    dao.deleteAll(entities);
    //}
    //
    //@Override
    //public boolean exits(ID id) {
    //    return dao.existsById(id);
    //}
    //
    //@Override
    //public boolean isNew(T entity) {
    //    return false;
    //}


}
